package sms_api

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"strconv"
	"strings"
	"time"

	"github.com/gogf/gf/v2/encoding/gjson"
	"github.com/gogf/gf/v2/os/gfile"
	"github.com/gogf/gf/v2/util/gconv"
)

// Config SMS API配置
type Config struct {
	// 服务配置
	Host    string `json:"host" yaml:"host"`       // 服务主机
	Port    int    `json:"port" yaml:"port"`       // 服务端口
	Debug   bool   `json:"debug" yaml:"debug"`     // 调试模式
	Timeout time.Duration `json:"timeout" yaml:"timeout"` // 请求超时

	// 提供商配置
	Provider string            `json:"provider" yaml:"provider"` // 当前提供商
	SpaceIoT *SpaceIoTConfig   `json:"space_iot,omitempty" yaml:"space_iot,omitempty"`
	Alibaba  *AlibabaConfig    `json:"alibaba,omitempty" yaml:"alibaba,omitempty"`
	Tencent  *TencentConfig    `json:"tencent,omitempty" yaml:"tencent,omitempty"`
	Huawei   *HuaweiConfig     `json:"huawei,omitempty" yaml:"huawei,omitempty"`

	// 重试配置
	Retry *RetryConfig `json:"retry,omitempty" yaml:"retry,omitempty"`

	// 速率限制配置
	RateLimit *RateLimitConfig `json:"rate_limit,omitempty" yaml:"rate_limit,omitempty"`

	// 批量处理配置
	Batch *BatchConfig `json:"batch,omitempty" yaml:"batch,omitempty"`

	// 缓存配置
	Cache *CacheConfig `json:"cache,omitempty" yaml:"cache,omitempty"`

	// 监控配置
	Metrics *MetricsConfig `json:"metrics,omitempty" yaml:"metrics,omitempty"`

	// 安全配置
	Security *SecurityConfig `json:"security,omitempty" yaml:"security,omitempty"`
}

// SpaceIoTConfig Space IoT SMS配置
type SpaceIoTConfig struct {
	BaseURL string `json:"base_url" yaml:"base_url"` // API基础URL
	Sign    string `json:"sign" yaml:"sign"`         // 签名
	Key     string `json:"key" yaml:"key"`           // 密钥
	Timeout time.Duration `json:"timeout" yaml:"timeout"` // 超时时间
}

// AlibabaConfig 阿里云SMS配置
type AlibabaConfig struct {
	AccessKeyID     string `json:"access_key_id" yaml:"access_key_id"`         // AccessKey ID
	AccessKeySecret string `json:"access_key_secret" yaml:"access_key_secret"` // AccessKey Secret
	Region          string `json:"region" yaml:"region"`                       // 地域
	Endpoint        string `json:"endpoint,omitempty" yaml:"endpoint,omitempty"` // 自定义端点
	Timeout         time.Duration `json:"timeout" yaml:"timeout"`               // 超时时间
}

// TencentConfig 腾讯云SMS配置
type TencentConfig struct {
	SecretID  string `json:"secret_id" yaml:"secret_id"`   // Secret ID
	SecretKey string `json:"secret_key" yaml:"secret_key"` // Secret Key
	Region    string `json:"region" yaml:"region"`         // 地域
	AppID     string `json:"app_id" yaml:"app_id"`         // 应用ID
	Timeout   time.Duration `json:"timeout" yaml:"timeout"`   // 超时时间
}

// HuaweiConfig 华为云SMS配置
type HuaweiConfig struct {
	AccessKey string `json:"access_key" yaml:"access_key"` // Access Key
	SecretKey string `json:"secret_key" yaml:"secret_key"` // Secret Key
	Region    string `json:"region" yaml:"region"`         // 地域
	ProjectID string `json:"project_id" yaml:"project_id"` // 项目ID
	Timeout   time.Duration `json:"timeout" yaml:"timeout"`   // 超时时间
}

// RetryConfig 重试配置
type RetryConfig struct {
	MaxAttempts    int           `json:"max_attempts" yaml:"max_attempts"`       // 最大重试次数
	InitialDelay   time.Duration `json:"initial_delay" yaml:"initial_delay"`     // 初始延迟
	MaxDelay       time.Duration `json:"max_delay" yaml:"max_delay"`             // 最大延迟
	BackoffFactor  float64       `json:"backoff_factor" yaml:"backoff_factor"`   // 退避因子
	JitterFactor   float64       `json:"jitter_factor" yaml:"jitter_factor"`     // 抖动因子
	CircuitTimeout time.Duration `json:"circuit_timeout" yaml:"circuit_timeout"` // 熔断器超时
}

// RateLimitConfig 速率限制配置
type RateLimitConfig struct {
	PerMinute int `json:"per_minute" yaml:"per_minute"` // 每分钟限制
	PerHour   int `json:"per_hour" yaml:"per_hour"`     // 每小时限制
	PerDay    int `json:"per_day" yaml:"per_day"`       // 每天限制
}

// BatchConfig 批量处理配置
type BatchConfig struct {
	Size           int           `json:"size" yaml:"size"`                     // 批量大小
	Timeout        time.Duration `json:"timeout" yaml:"timeout"`               // 批量超时
	WorkerPoolSize int           `json:"worker_pool_size" yaml:"worker_pool_size"` // 工作池大小
	Concurrency    int           `json:"concurrency" yaml:"concurrency"`       // 并发数
}

// CacheConfig 缓存配置
type CacheConfig struct {
	TTL  time.Duration `json:"ttl" yaml:"ttl"`   // 缓存TTL
	Size int           `json:"size" yaml:"size"` // 缓存大小
}

// MetricsConfig 监控配置
type MetricsConfig struct {
	Enabled    bool          `json:"enabled" yaml:"enabled"`       // 是否启用
	Interval   time.Duration `json:"interval" yaml:"interval"`     // 收集间隔
	Retention  time.Duration `json:"retention" yaml:"retention"`   // 保留时间
	ExportPath string        `json:"export_path" yaml:"export_path"` // 导出路径
}

// SecurityConfig 安全配置
type SecurityConfig struct {
	EnableSignature bool          `json:"enable_signature" yaml:"enable_signature"` // 启用签名验证
	SignatureKey    string        `json:"signature_key" yaml:"signature_key"`       // 签名密钥
	KeyRotation     time.Duration `json:"key_rotation" yaml:"key_rotation"`         // 密钥轮换间隔
	IPWhitelist     []string      `json:"ip_whitelist" yaml:"ip_whitelist"`         // IP白名单
	EncryptionKey   string        `json:"encryption_key" yaml:"encryption_key"`     // 加密密钥
}

// DefaultConfig 返回默认配置
func DefaultConfig() *Config {
	return &Config{
		Host:     DefaultHost,
		Port:     DefaultPort,
		Debug:    DefaultDebug,
		Timeout:  DefaultTimeout,
		Provider: DefaultProvider,
		SpaceIoT: &SpaceIoTConfig{
			BaseURL: DefaultSpaceIoTBaseURL,
			Timeout: DefaultTimeout,
		},
		Retry: &RetryConfig{
			MaxAttempts:    DefaultMaxAttempts,
			InitialDelay:   DefaultInitialDelay,
			MaxDelay:       DefaultMaxDelay,
			BackoffFactor:  DefaultBackoffFactor,
			JitterFactor:   DefaultJitterFactor,
			CircuitTimeout: DefaultCircuitTimeout,
		},
		RateLimit: &RateLimitConfig{
			PerMinute: DefaultRateLimitPerMinute,
			PerHour:   DefaultRateLimitPerHour,
			PerDay:    DefaultRateLimitPerDay,
		},
		Batch: &BatchConfig{
			Size:           DefaultBatchSize,
			Timeout:        DefaultBatchTimeout,
			WorkerPoolSize: DefaultWorkerPoolSize,
			Concurrency:    DefaultWorkerPoolSize,
		},
		Cache: &CacheConfig{
			TTL:  DefaultCacheTTL,
			Size: DefaultCacheSize,
		},
		Metrics: &MetricsConfig{
			Enabled:   true,
			Interval:  time.Minute,
			Retention: 24 * time.Hour,
		},
		Security: &SecurityConfig{
			EnableSignature: false,
			KeyRotation:     24 * time.Hour,
		},
	}
}

// LoadConfigFromEnv 从环境变量加载配置
func LoadConfigFromEnv() *Config {
	config := DefaultConfig()

	// 服务配置
	if host := os.Getenv(ConfigKeyHost); host != "" {
		config.Host = host
	}
	if port := os.Getenv(ConfigKeyPort); port != "" {
		if p, err := strconv.Atoi(port); err == nil {
			config.Port = p
		}
	}
	if debug := os.Getenv(ConfigKeyDebug); debug != "" {
		config.Debug = gconv.Bool(debug)
	}
	if provider := os.Getenv(ConfigKeyProvider); provider != "" {
		config.Provider = provider
	}

	// Space IoT配置
	if baseURL := os.Getenv(ConfigKeySpaceIoTBaseURL); baseURL != "" {
		if config.SpaceIoT == nil {
			config.SpaceIoT = &SpaceIoTConfig{}
		}
		config.SpaceIoT.BaseURL = baseURL
	}
	if sign := os.Getenv(ConfigKeySpaceIoTSign); sign != "" {
		if config.SpaceIoT == nil {
			config.SpaceIoT = &SpaceIoTConfig{}
		}
		config.SpaceIoT.Sign = sign
	}
	if key := os.Getenv(ConfigKeySpaceIoTKey); key != "" {
		if config.SpaceIoT == nil {
			config.SpaceIoT = &SpaceIoTConfig{}
		}
		config.SpaceIoT.Key = key
	}

	// 阿里云配置
	if accessKeyID := os.Getenv(ConfigKeyAlibabaAccessKeyID); accessKeyID != "" {
		if config.Alibaba == nil {
			config.Alibaba = &AlibabaConfig{}
		}
		config.Alibaba.AccessKeyID = accessKeyID
	}
	if accessKeySecret := os.Getenv(ConfigKeyAlibabaAccessKeySecret); accessKeySecret != "" {
		if config.Alibaba == nil {
			config.Alibaba = &AlibabaConfig{}
		}
		config.Alibaba.AccessKeySecret = accessKeySecret
	}
	if region := os.Getenv(ConfigKeyAlibabaRegion); region != "" {
		if config.Alibaba == nil {
			config.Alibaba = &AlibabaConfig{}
		}
		config.Alibaba.Region = region
	}

	// 重试配置
	if maxAttempts := os.Getenv(ConfigKeyRetryMaxAttempts); maxAttempts != "" {
		if attempts, err := strconv.Atoi(maxAttempts); err == nil {
			config.Retry.MaxAttempts = attempts
		}
	}
	if initialDelay := os.Getenv(ConfigKeyRetryInitialDelay); initialDelay != "" {
		if delay, err := time.ParseDuration(initialDelay); err == nil {
			config.Retry.InitialDelay = delay
		}
	}
	if maxDelay := os.Getenv(ConfigKeyRetryMaxDelay); maxDelay != "" {
		if delay, err := time.ParseDuration(maxDelay); err == nil {
			config.Retry.MaxDelay = delay
		}
	}

	// 速率限制配置
	if perMinute := os.Getenv(ConfigKeyRateLimitPerMinute); perMinute != "" {
		if limit, err := strconv.Atoi(perMinute); err == nil {
			config.RateLimit.PerMinute = limit
		}
	}
	if perHour := os.Getenv(ConfigKeyRateLimitPerHour); perHour != "" {
		if limit, err := strconv.Atoi(perHour); err == nil {
			config.RateLimit.PerHour = limit
		}
	}

	// 批量处理配置
	if batchSize := os.Getenv(ConfigKeyBatchSize); batchSize != "" {
		if size, err := strconv.Atoi(batchSize); err == nil {
			config.Batch.Size = size
		}
	}
	if workerPoolSize := os.Getenv(ConfigKeyWorkerPoolSize); workerPoolSize != "" {
		if size, err := strconv.Atoi(workerPoolSize); err == nil {
			config.Batch.WorkerPoolSize = size
			config.Batch.Concurrency = size
		}
	}

	return config
}

// LoadConfigFromFile 从文件加载配置
func LoadConfigFromFile(filePath string) (*Config, error) {
	if !gfile.Exists(filePath) {
		return nil, NewValidationError("config_file", "exists", filePath, "配置文件不存在")
	}

	content := gfile.GetContents(filePath)
	if content == "" {
		return nil, NewValidationError("config_file", "content", filePath, "配置文件内容为空")
	}

	config := DefaultConfig()
	if err := gjson.Unmarshal([]byte(content), config); err != nil {
		return nil, NewValidationError("config_file", "format", filePath, "配置文件格式错误: "+err.Error())
	}

	return config, nil
}

// SaveConfigToFile 保存配置到文件
func (c *Config) SaveConfigToFile(filePath string) error {
	content, err := gjson.Marshal(c)
	if err != nil {
		return NewValidationError("config", "marshal", c, "配置序列化失败: "+err.Error())
	}

	if err := gfile.PutContents(filePath, string(content)); err != nil {
		return NewValidationError("config_file", "write", filePath, "配置文件写入失败: "+err.Error())
	}

	return nil
}

// Validate 验证配置
func (c *Config) Validate() error {
	// 验证基本配置
	if c.Host == "" {
		return NewValidationError("host", "required", c.Host, "主机地址不能为空")
	}
	if c.Port <= 0 || c.Port > 65535 {
		return NewValidationError("port", "range", c.Port, "端口号无效")
	}
	if c.Provider == "" {
		return NewValidationError("provider", "required", c.Provider, "SMS提供商不能为空")
	}

	// 验证提供商配置
	switch c.Provider {
	case ProviderSpaceIoT:
		if c.SpaceIoT == nil {
			return NewValidationError("space_iot", "required", nil, "Space IoT配置不能为空")
		}
		if err := c.SpaceIoT.Validate(); err != nil {
			return err
		}
	case ProviderAlibaba:
		if c.Alibaba == nil {
			return NewValidationError("alibaba", "required", nil, "阿里云配置不能为空")
		}
		if err := c.Alibaba.Validate(); err != nil {
			return err
		}
	case ProviderTencent:
		if c.Tencent == nil {
			return NewValidationError("tencent", "required", nil, "腾讯云配置不能为空")
		}
		if err := c.Tencent.Validate(); err != nil {
			return err
		}
	case ProviderHuawei:
		if c.Huawei == nil {
			return NewValidationError("huawei", "required", nil, "华为云配置不能为空")
		}
		if err := c.Huawei.Validate(); err != nil {
			return err
		}
	default:
		return NewValidationError("provider", "enum", c.Provider, "不支持的SMS提供商")
	}

	return nil
}

// Validate 验证Space IoT配置
func (c *SpaceIoTConfig) Validate() error {
	if c.BaseURL == "" {
		return NewValidationError("base_url", "required", c.BaseURL, "Base URL不能为空")
	}
	if c.Sign == "" {
		return NewValidationError("sign", "required", c.Sign, "签名不能为空")
	}
	if c.Key == "" {
		return NewValidationError("key", "required", c.Key, "密钥不能为空")
	}
	return nil
}

// Validate 验证阿里云配置
func (c *AlibabaConfig) Validate() error {
	if c.AccessKeyID == "" {
		return NewValidationError("access_key_id", "required", c.AccessKeyID, "AccessKey ID不能为空")
	}
	if c.AccessKeySecret == "" {
		return NewValidationError("access_key_secret", "required", c.AccessKeySecret, "AccessKey Secret不能为空")
	}
	if c.Region == "" {
		c.Region = DefaultAlibabaRegion
	}
	return nil
}

// Validate 验证腾讯云配置
func (c *TencentConfig) Validate() error {
	if c.SecretID == "" {
		return NewValidationError("secret_id", "required", c.SecretID, "Secret ID不能为空")
	}
	if c.SecretKey == "" {
		return NewValidationError("secret_key", "required", c.SecretKey, "Secret Key不能为空")
	}
	if c.AppID == "" {
		return NewValidationError("app_id", "required", c.AppID, "App ID不能为空")
	}
	return nil
}

// Validate 验证华为云配置
func (c *HuaweiConfig) Validate() error {
	if c.AccessKey == "" {
		return NewValidationError("access_key", "required", c.AccessKey, "Access Key不能为空")
	}
	if c.SecretKey == "" {
		return NewValidationError("secret_key", "required", c.SecretKey, "Secret Key不能为空")
	}
	if c.ProjectID == "" {
		return NewValidationError("project_id", "required", c.ProjectID, "Project ID不能为空")
	}
	return nil
}

// UpdateProvider 更新提供商配置
func (c *Config) UpdateProvider(provider string, config interface{}) error {
	switch provider {
	case ProviderSpaceIoT:
		if spaceIoTConfig, ok := config.(*SpaceIoTConfig); ok {
			c.SpaceIoT = spaceIoTConfig
			c.Provider = provider
		} else {
			return NewValidationError("config", "type", config, "配置类型不匹配")
		}
	case ProviderAlibaba:
		if alibabaConfig, ok := config.(*AlibabaConfig); ok {
			c.Alibaba = alibabaConfig
			c.Provider = provider
		} else {
			return NewValidationError("config", "type", config, "配置类型不匹配")
		}
	case ProviderTencent:
		if tencentConfig, ok := config.(*TencentConfig); ok {
			c.Tencent = tencentConfig
			c.Provider = provider
		} else {
			return NewValidationError("config", "type", config, "配置类型不匹配")
		}
	case ProviderHuawei:
		if huaweiConfig, ok := config.(*HuaweiConfig); ok {
			c.Huawei = huaweiConfig
			c.Provider = provider
		} else {
			return NewValidationError("config", "type", config, "配置类型不匹配")
		}
	default:
		return NewValidationError("provider", "enum", provider, "不支持的SMS提供商")
	}

	return nil
}

// GetCurrentProviderConfig 获取当前提供商配置
func (c *Config) GetCurrentProviderConfig() interface{} {
	switch c.Provider {
	case ProviderSpaceIoT:
		return c.SpaceIoT
	case ProviderAlibaba:
		return c.Alibaba
	case ProviderTencent:
		return c.Tencent
	case ProviderHuawei:
		return c.Huawei
	default:
		return nil
	}
}

// Clone 克隆配置
func (c *Config) Clone() *Config {
	content, _ := gjson.Marshal(c)
	newConfig := &Config{}
	gjson.Unmarshal(content, newConfig)
	return newConfig
}